package com.turing.post.datasorting.impl;

import java.math.BigDecimal;
import java.math.BigInteger;
import java.math.RoundingMode;
import java.util.Date;
import java.util.HashMap;
import java.util.List;

import javax.ejb.EJB;
import javax.ejb.Local;
import javax.ejb.Remote;
import javax.ejb.Stateless;
import javax.ejb.TransactionAttribute;

import com.turing.post.datasorting.util.DataSortApplicationException;
import com.turing.post.datasorting.util.InComeSortingBusiness;
import com.turing.post.organization.util.IssueCompany;
import com.turing.post.organization.util.IssueCompanyDao;
import com.turing.post.organization.util.MerchantFeeSettlementPolicy;
import com.turing.post.organization.util.MerchantFeeSettlementPolicyBusiness;
import com.turing.post.organization.util.MerchantFeeSettlementPolicyDao;
import com.turing.post.report.util.IncomeDaySettlement;
import com.turing.post.report.util.IncomeDaySettlementDao;
import com.turing.post.report.util.MerchantBusinessDaySettlement;
import com.turing.post.report.util.MerchantBusinessDaySettlementDao;
import com.turing.post.report.util.MerchantDaySettlement;
import com.turing.post.report.util.MerchantDaySettlementDao;
import com.turing.post.report.util.MerchantPastIncome;
import com.turing.post.report.util.MerchantPastIncomeDao;
import com.turing.post.report.util.MerchantPastIncomeDetail;
import com.turing.post.report.util.MerchantPastIncomeDetailDao;
import com.turing.post.transaction.util.MchBsTypeTradDetailDao;
import com.turing.post.util.PCPSApplicationException;
import com.turing.post.util.PCPSUtil;

/**
 * 清分业务实现类
 * 
 * @author YangShuo
 * 
 */

@Stateless(mappedName = "datasorting.impl.InComeSortingBusinessImpl")
@Remote
@Local
public class InComeSortingBusinessImpl implements InComeSortingBusiness {

	@EJB(mappedName = "organization.impl.MerchantFeeSettlementPolicyBusinessImpl")
	private MerchantFeeSettlementPolicyBusiness MerchantFeeSettlementPolicyBusinessImpl;

	@EJB(mappedName = "organization.impl.MerchantFeeSettlementPolicyDaoImpl")
	private MerchantFeeSettlementPolicyDao MerchantFeeSettlementPolicyDaoImpl;

	@EJB(mappedName = "report.impl.IncomeDaySettlementDaoImpl")
	private IncomeDaySettlementDao IncomeDaySettlementDaoImpl;

	@EJB(mappedName = "report.impl.MerchantPastIncomeDetailDaoImpl")
	private MerchantPastIncomeDetailDao MerchantPastIncomeDetailDaoImpl;

	@EJB(mappedName = "report.impl.MerchantDaySettlementDaoImpl")
	private MerchantDaySettlementDao MerchantDaySettlementDaoImpl;

	@EJB(mappedName = "report.impl.MerchantBusinessDaySettlementDaoImpl")
	private MerchantBusinessDaySettlementDao MerchantBusinessDaySettlementDaoImpl;
	
	@EJB(mappedName = "transaction.impl.MchBsTypeTradDetailDaoImpl")
	private MchBsTypeTradDetailDao MchBsTypeTradDetailDaoImpl;
	
	@EJB(mappedName = "organization.impl.IssueCompanyDaoImpl")
	private IssueCompanyDao IssueCompanyDaoImpl;

	@EJB(mappedName = "report.impl.MerchantPastIncomeDaoImpl")
	private MerchantPastIncomeDao MerchantPastIncomeDaoImpl;
	
	
	
	
	/**
	 * 校验某发卡商某日所有商户的结算策略设置是否合法
	 * @param issueCompanyNo
	 * @param trandate
	 * @return ok代表通过其他情况为错误信息
	 */
	@Override
	public String checkMerchantFeeSettlementPolicy(String issueCompanyNo, Date trandate)
	{
		// 取所有有交易的商户和激活商户的并集
//		List<Merchant> mchlist = merchantDaoImpl
//				.getActivateMerchantListByIssueCompanyNo(issueCompanyNo);
		
		List<String> mchlist = MchBsTypeTradDetailDaoImpl
				.getAllMerchantBusinessMerchantNo(issueCompanyNo, trandate);
		if(mchlist.size()<=0)
			return "系统中没有商户";
	
		for(String merchantno:mchlist)
		{
			// 1根据merchantno和trandate取得该商户该日的结算比率。先运行判断策略
			String checkresult = MerchantFeeSettlementPolicyBusinessImpl
					.checkMerchantFeeSettlementPolicyByMerchantNoAndTrandate(
							merchantno, trandate);
			if (!checkresult.equals("ok")) // 验证该日结算比率，如验证不通过返回。
				return	 "商户"+merchantno+checkresult;
			
	
			// 取得结算比率的集合			
			List<MerchantFeeSettlementPolicy> mfsplist = MerchantFeeSettlementPolicyDaoImpl
					.getEffectMerchantFeeSettlementPolicyList(merchantno, trandate);
			if (mfsplist.size() < 1)
				return "商户"+merchantno+"未找到合适的结算比率";
			
		}
		return "ok";
	}
	
	// 按商户、日期进行数据清分
	@Override
	@TransactionAttribute(javax.ejb.TransactionAttributeType.REQUIRES_NEW)
	public void inComeSort(String merchantno, Date trandate)
			throws PCPSApplicationException {

		PCPSUtil.Log("开始进行商户" + merchantno + "--" + trandate + "s数据。");
		// TODO Auto-generated method stub
		int feeratio = 0; // 结算比率
		BigDecimal totalconsume = new BigDecimal(0);// 本日消费合计
		BigDecimal totalprofit = new BigDecimal(0);// 本日利润合计
		BigDecimal cost = new BigDecimal(0);// 本日成本
		BigDecimal issueFund=BigDecimal.ZERO; //本日发卡商分成
		BigInteger pastissueFund=BigInteger.ZERO; //本日发卡商分成追溯
		IssueCompany ic=IssueCompanyDaoImpl.getIssueCompanyByIssueCompanyNo(merchantno.substring(0,6));
		int crossratio = ic.getMCommissionRatio();// 得到跨地区结算比率
		int commissionRatio = ic.getCommissionRatio();//得到总公司抽成比率
		crossratio=(crossratio*10000)/(10000-commissionRatio); //销售机构与商户开发机构两两分成的比率需要换算，用(M分配比率*10000)/（10000-总公司抽成）
		
		BigInteger totaltracing = new BigInteger("0");// 该商户该日追溯合计
		HashMap<String, MerchantFeeSettlementPolicy> policyhm = new HashMap<String, MerchantFeeSettlementPolicy>(); // 当结算方式是按业务类型结算时，用来保存结算方式的哈希
		PCPSUtil.Log("开始获取MerchantDaySettlement对象。");
		// 得到该商户该日的MerchantDaySettlement对象
		MerchantDaySettlement mds = MerchantDaySettlementDaoImpl
				.getMerchantDaySettlementByTranDate_Merchantno(merchantno,
						trandate);		
		if (mds == null) {
			PCPSUtil.Log("得到该商户该日的MerchantDaySettlement对象失败");
//			System.out.println("得到该商户该日的MerchantDaySettlement对象失败");
			//如果未取到对象，则直接结束，不再进行各种判定产生日终中断。
			return;
		} else {
//			System.out.println("mds.getMerchantNo()=================="
//					+ mds.getMerchantNo());
//			System.out.println("mds.getConsume()=================="
//					+ mds.getConsume());
//			System.out.println("mds.getCancelPaid()=================="
//					+ mds.getCancelPaid());
		}

		PCPSUtil.Log("运行结算比率校验方法。");
		// 1根据merchantno和trandate取得该商户该日的结算比率。先运行判断策略
		String checkresult = MerchantFeeSettlementPolicyBusinessImpl
				.checkMerchantFeeSettlementPolicyByMerchantNoAndTrandate(
						merchantno, trandate);
		if (!checkresult.equals("ok")) // 验证该日结算比率，如验证不通过返回。
			throw new DataSortApplicationException(
					DataSortApplicationException.ERRCODE_CATEGORY_APPLICATION,
					checkresult);
		PCPSUtil.Log("结算比率校验通过。");
//		System.out.println("结算比率校验通过。");

		// 取得达到阀值的结算比率的集合
		PCPSUtil.Log("取得达到阀值的结算比率的集合。");
		List<MerchantFeeSettlementPolicy> mfsplist = MerchantFeeSettlementPolicyDaoImpl
				.getEffectMerchantFeeSettlementPolicyList(merchantno, trandate);
		if (mfsplist.size() < 1)
			throw new DataSortApplicationException(
					DataSortApplicationException.ERRCODE_CATEGORY_APPLICATION,
					"未找到合适的结算比率");
		PCPSUtil.Log("成功取得结算比率集合。");

		// 开始过滤结算比率，取得集合中最大的费率
		PCPSUtil.Log("开始过滤结算比率，取得集合中最大的费率");
//		System.out.println("开始过滤结算比率，取得集合中最大的费率");
		MerchantFeeSettlementPolicy ms = null;
		for (int i = 0; i < mfsplist.size(); i++) {

			ms = mfsplist.get(i);
			// 将结算比率按照业务类型放入hash表
			policyhm.put(ms.getBusinessType(), ms);
			if (i == 0) {
				// 第一个循环，给feeratio
				feeratio = ms.getFeeRatio().intValue();
			} else {
				PCPSUtil.Log("多条结算比率处理。");
				// 不止一条记录时，比较，最终返回最大的feeratio
				if (ms.getFeeRatio().intValue() > feeratio)
					feeratio = ms.getFeeRatio().intValue();
			}
		}
		
		
		//差额追溯时，进入判断，如已经追溯过不再追溯，如果没有追溯过进行追溯。
		if(ms.getPolicy().equals(MerchantFeeSettlementPolicy.POLICY_LADDERRETROSPECTIVE))
		{
//			System.out.println("进入追溯");
			BigInteger[] bi=getPastIncome(ms,trandate,null);
			totaltracing=bi[0];
			pastissueFund=bi[1];
		}

		// 如果是差额无追述，需要用费率集合计算收入
		if (ms.getPolicy().equals(
				MerchantFeeSettlementPolicy.POLICY_NORETROSPECTIVE)) {
			PCPSUtil.Log("进入差额无追溯处理。");
			// 从mds中取得本日有效消费合计。
			totalconsume = new BigDecimal(mds.getConsume().subtract(
					mds.getCancelPaid()));
			PCPSUtil.Log("从mds中取得本日有效消费合计==" + totalconsume);
			// 得到本日之前的消费总额
			long totallimit = MerchantDaySettlementDaoImpl
					.getLimitAmountByDateDecreaseOneDay(merchantno, ms
							.getPolicyStartDate(), trandate);
			PCPSUtil.Log("得到本日之前的消费总额。" + totallimit);

			if (totallimit > mfsplist.get(mfsplist.size() - 1).getLimitAmount()
					.longValue()) {
				// 如果本日消费全部在最大的比率区间内，按照此比率进行计算
				// 先计算商户与发卡商之间的本日账务关系，计算出应结款项和利润
				// 从mds中取得本日有效消费合计。
				PCPSUtil.Log("消费全部在最大的比率区间内");
				totalconsume = new BigDecimal(mds.getConsume().subtract(
						mds.getCancelPaid()));
				PCPSUtil.Log("本日有效消费合计。" + totalconsume);
				// 根据比率计算出成本
				cost = totalconsume.multiply(new BigDecimal(10000 - mfsplist
						.get(mfsplist.size() - 1).getFeeRatio().intValue())); // 乘以万分率的比率
				cost = cost.divide(new BigDecimal(10000));// 除以10000
				PCPSUtil.Log("计算出成本。" + cost);
				// 用总额减去成本算出总利润收入
				totalprofit = totalconsume.subtract(cost);
				PCPSUtil.Log("用总额减去成本算出总利润收入。" + totalprofit);
			} else {
				// 本日消费垮了多个费率区间，分别计算
				PCPSUtil.Log("本日消费垮了多个费率区间");
				// 循环费率集合，取得多个费率档次，依次计算各个档次收入及成本,从阀值最大的规则开始循环
				MerchantFeeSettlementPolicy ms1 = null;
				// 从mds中取得本日有效消费合计。
				totalconsume = new BigDecimal(mds.getConsume().subtract(
						mds.getCancelPaid()));
				long totalconsume_todayreserve = totalconsume.longValue();// 用来递减的剩余本日消费总额
				PCPSUtil.Log("用来递减的剩余本日消费总额==" + totalconsume_todayreserve);
				for (int i = mfsplist.size() - 1; i >= 0; i--) {
					PCPSUtil.Log("进入多个费率区间处理");
					ms1 = mfsplist.get(i);
					// 取得当前区间的消费总额 本日之前消费总额+今日剩余消费总额-当前策略阀值
					BigDecimal totalconsume_current = new BigDecimal(totallimit
							+ totalconsume_todayreserve
							- ms1.getLimitAmount().longValue());
					PCPSUtil.Log("取得当前区间的消费总额  本日之前消费总额+今日剩余消费总额-当前策略阀值="
							+ totalconsume_current);
					// 如果结果大于等于剩余的本日消费，则当前区间消费额等于剩余本日消费
					if (totalconsume_current.longValue() >= totalconsume_todayreserve)
						totalconsume_current = new BigDecimal(
								totalconsume_todayreserve);
					PCPSUtil.Log("处理过后的本区间有效消费==" + totalconsume_current);

					// 依照当前消费总额计算当前成本与利润
					// 根据比率计算出成本
					BigDecimal cost_current = totalconsume_current
							.multiply(new BigDecimal(10000 - ms1.getFeeRatio()
									.intValue())); // 乘以万分率的比率
					cost_current = cost_current.divide(new BigDecimal(10000));// 除以10000
					PCPSUtil.Log("依照当前消费总额计算当前成本=" + cost_current);
					// 用总额减去成本算出当前利润收入
					BigDecimal totalprofit_current = totalconsume_current
							.subtract(cost_current);
					PCPSUtil.Log("依照当前消费总额计算当前成利润=" + totalprofit_current);
					// 所得到的当前结果累加进总收入和总成本
					cost = cost.add(cost_current);
					totalprofit = totalprofit.add(totalprofit_current);

					// 将用来递减的本日消费总额进行递减
					totalconsume_todayreserve = totalconsume_todayreserve
							- totalconsume_current.longValue();
					PCPSUtil.Log("将用来递减的本日消费总额进行递减="
							+ totalconsume_todayreserve + "-"
							+ totalconsume_current.longValue());
				}
			}
			// 因为使用了多个费率，计算出平均费率以便记录入数据库
			if (totalconsume.abs().compareTo(BigDecimal.valueOf(0.0001)) < 0)
				feeratio = 0;
			else
				feeratio = 10000 - totalprofit.divide(totalconsume, 4,
						RoundingMode.HALF_DOWN).multiply(
						new BigDecimal("10000")).intValue();
		}
		// 如果是固定费率或者阶梯追溯 则使用单一比率进行计算
		else if (ms.getPolicy().equals(
				MerchantFeeSettlementPolicy.POLICY_FIXEDRATE)
				|| ms.getPolicy().equals(
						MerchantFeeSettlementPolicy.POLICY_LADDERRETROSPECTIVE)) {
			PCPSUtil.Log("进入固定费率和阶梯费率处理。");
			// 先计算商户与发卡商之间的本日账务关系，计算出应结款项和利润
			// 从mds中取得本日有效消费合计。
			totalconsume = new BigDecimal(mds.getConsume().subtract(
					mds.getCancelPaid()));
			// 根据比率计算出成本
			cost = totalconsume.multiply(new BigDecimal(10000-feeratio)); // 乘以万分率的比率
			cost = cost.divide(new BigDecimal(10000));// 除以10000
			// 用总额减去成本算出总利润收入
			totalprofit = totalconsume.subtract(cost);
		}
		// 如果是按业务类型结算则分类型使用单一比率进行计算
		else if (ms.getPolicy().equals(
				MerchantFeeSettlementPolicy.POLICY_BYBUSINESSTYPE)) {
			PCPSUtil.Log("进入业务类型结算处理。");
			// 首先取得按业务类型的分类数据
			List<MerchantBusinessDaySettlement> mblist = MerchantBusinessDaySettlementDaoImpl
					.getMerchantBusinessDaySettlementByTrandateAndMerchantno(
							trandate, merchantno);
			for (MerchantBusinessDaySettlement mb : mblist) {
				// 根据业务类型取得结算比率
				MerchantFeeSettlementPolicy b_ms = (MerchantFeeSettlementPolicy) policyhm
						.get(mb.getBusinessType());
				mb.setSettRatio(b_ms.getFeeRatio());// 将使用的结算比率放入对象
				// 计算有效交易额 =消费+现金-退货 并将计算好的数据累加进总数据
				BigDecimal businessConsume = new BigDecimal(mb.getConsume()
						.add(mb.getOtherPaid()).subtract(mb.getCancelPaid()));
				totalconsume = totalconsume.add(businessConsume);// 根据业务类型取得结算比率
																	// 消费+现金-退货
				// 计算成本=有效交易额x结算比率 并将计算好的数据累加进总数据
				BigDecimal businessCost = businessConsume
						.multiply(new BigDecimal(new BigInteger("10000")
								.subtract(b_ms.getFeeRatio())));
				businessCost = businessCost.divide(new BigDecimal(10000));// 除以10000
				mb.setCost(businessCost.toBigInteger()); // 将计算好的数据放入对象
				cost = cost.add(businessCost);
				// 用有效交易额减去成本算出利润收入 并将计算好的数据累加进总数据
				BigDecimal businesstotalprofit = businessConsume
						.subtract(businessCost);
				mb.setIncome(businesstotalprofit.toBigInteger()); // 将计算好的数据放入对象
				totalprofit = totalprofit.add(businesstotalprofit);

				// 将填入结算比率，成本，利润的对象更新数据库
				MerchantBusinessDaySettlementDaoImpl.update(mb);
			}
			// 因为使用了多个费率，计算出平均费率以便记录入数据库
			if (totalconsume.abs().compareTo(BigDecimal.valueOf(0.0001)) < 0)
				feeratio = 0;
			else
				feeratio = 10000 - totalprofit.divide(totalconsume, 4,
						RoundingMode.HALF_DOWN).multiply(
						new BigDecimal("10000")).intValue();
		}

		//计算出本商户利润的发卡商分成
		issueFund=totalprofit.multiply(new BigDecimal(commissionRatio).divide(new BigDecimal("10000"))); 
		
		long totalprofit_l = totalprofit.subtract(issueFund).longValue();// 用来递减的可分配总利润收入,要用总利润减去发卡商分成
		// 取得该日与该商户发生交易的销售机构的扎帐数据集合
		PCPSUtil.Log("取得该日与该商户发生交易的销售机构的扎帐数据集合。");
		List<IncomeDaySettlement> incomedaysettlementlist = IncomeDaySettlementDaoImpl
				.getIncomeDaySettlementByMerchantNoAndTrandate(merchantno,
						trandate);
		// 循环销售机构的数据集合，根据结算比率算出利润，成本。如产生跨地区消费，计算跨地区消费
		PCPSUtil.Log("循环销售机构的数据集合，根据结算比率算出利润，成本。如产生跨地区消费，计算跨地区消费");
		IncomeDaySettlement ids = null;
		for (int i = 0; i < incomedaysettlementlist.size(); i++) {
			ids = incomedaysettlementlist.get(i);
			// 计算出该商户在该机构该日的总利润,处理0值
			long income=0;
			if(totalconsume.abs().compareTo(BigDecimal.valueOf(0.0001)) < 0)
				income=0;
			else
				income = totalprofit.multiply(
					new BigDecimal(ids.getConsume().doubleValue()
							/ totalconsume.doubleValue())).longValue();
			PCPSUtil.Log("计算出该商户在该机构该日的总利润");
			// 如果是最后一条记录，或者利润已经分配完了，则用递减的总利润代替利润
			if ((i == (incomedaysettlementlist.size() - 1))
					|| totalprofit_l <= 0)
				income = totalprofit_l;
			PCPSUtil.Log("如果是最后一条记录，或者利润已经分配完了，则用递减的总利润代替利润");
			// 比对收益机构是否一致，如不一致，分项计算收益，否侧所有收益。
			PCPSUtil.Log("比对收益机构是否一致，如不一致，分项计算收益，否侧所有收益");
			if (ids.getMIncomeBranchId().compareTo(ids.getSIncomeBranchId()) == 0) {
				// 一致，全部收入都是S收益机构收入。
				ids.setSIncome(new BigInteger(String.valueOf(income)));
				ids.setMIncome(new BigInteger("0"));
			} else {
				// 不一致，S收益机构与M收益机构分成。
				ids.setSIncome(new BigInteger(String.valueOf(income - income
						* crossratio / 10000)));
				ids.setMIncome(new BigInteger(String.valueOf(income
						- ids.getSIncome().longValue())));
			}
			// 获取S追溯收入
			PCPSUtil.Log("获取S追溯收入");
			ids.setSPastIncome(MerchantPastIncomeDetailDaoImpl
					.getTotalSIncomeByMerchantNo_Trandate_Salbranchno(
							merchantno, trandate, ids.getSaleBranchNo()));
			// 获取M追溯收入
			PCPSUtil.Log("获取M追溯收入");
			ids.setMPastIncome(MerchantPastIncomeDetailDaoImpl
					.getTotalMIncomeByMerchantNo_Trandate_Salbranchno(
							merchantno, trandate, ids.getSaleBranchNo()));
			// 结算比率
			PCPSUtil.Log("结算比率");
			ids.setSettRatio(new BigInteger(String.valueOf(feeratio)));

			// 修改数据，将计算好的收入和追溯收入计入数据库
			PCPSUtil.Log("修改数据，将计算好的收入和追溯收入计入数据库");
			IncomeDaySettlementDaoImpl.update(ids);

			// 追溯合计累加
			totaltracing.add(ids.getSPastIncome());
			totaltracing.add(ids.getMPastIncome());

			// 总利润减去已分配的利润
			totalprofit_l = totalprofit_l - income;
			// 递减的利润不可为负
			if (totalprofit_l < 0)
				totalprofit_l = 0;
		}
		// 各个销售机构利润分配完毕后，生成与商户的结算数据，更新商户结算表数据。
		PCPSUtil.Log("各个销售机构利润分配完毕后，生成与商户的结算数据，更新商户结算表数据。");
		// 将结算数据放入
		mds.setSettRatio(new BigInteger(String.valueOf(feeratio)));
		mds.setIncome(new BigInteger(String.valueOf(totalprofit.longValue())));
		mds.setCost(new BigInteger(String.valueOf(cost.longValue())));
		mds.setPastIncome(totaltracing);
		mds.setPaidFund(mds.getCost().subtract(mds.getPastIncome()).subtract(
				mds.getDeposit()));// 成本减去追溯减去充值
		mds.setIssueFund(new BigInteger(String.valueOf(issueFund.longValue())).add(pastissueFund));//本日发卡商分成，里面含有被追溯的部分

		// 更新数据
		MerchantDaySettlementDaoImpl.update(mds);
	}
	
	@Override
	@TransactionAttribute(javax.ejb.TransactionAttributeType.REQUIRES_NEW)
	public BigInteger[] getPastIncome(MerchantFeeSettlementPolicy ms,Date trandate,BigInteger operid) throws PCPSApplicationException
	{
		//1.首先判断该策略有没有进行追溯，有返回0，无进行追溯。
		if(MerchantPastIncomeDaoImpl.check_FeePolicy(ms.getFeePolicyId()))
			return new BigInteger[]{BigInteger.ZERO,BigInteger.ZERO};
		
		//2.开始追溯，首先计算出本日之前的收入合计并减去已结算的收入和已追溯的收入
		//先使用本日日期减去一天，得到追溯的截止日期
		Date enddate=new Date(trandate.getTime()-(1000*60*60*24));
		//取得本日之前的消费总额
		long totallimit = MerchantDaySettlementDaoImpl
		.getLimitAmountByDate(ms.getMerchantNo(), ms
				.getPolicyStartDate(), enddate);
		
		//计算出本日之前消费总额产生的按新比率结算的收入，这个是应得收入，包含了以前的收入	
		long pastIncome=totallimit*ms.getFeeRatio().longValue()/10000; //应得收入
		//计算出已经结算的收入合计
		//原始收入
		long oldincome=MerchantDaySettlementDaoImpl.getAllIncomeByDate(ms.getMerchantNo(), ms
				.getPolicyStartDate(),  enddate);
		//已追溯收入
		long oldpastincome=MerchantPastIncomeDetailDaoImpl.getAllIncomeByDate(ms.getMerchantNo(), ms
				.getPolicyStartDate(),  enddate);
		//计算出实际应追溯收入
		long realpastincome=pastIncome-oldincome-oldpastincome;
		//将实际应追溯收入复制一份用于递减
		long s_realpastincome=realpastincome;
		
		//3.总应追溯收入计算好后，取得IncomeDaySettlement数据按日进行追溯收入的分配
		//按商户号，时间段取得IncomeDaySettlement的集合
		List<IncomeDaySettlement> ilist=IncomeDaySettlementDaoImpl
			.getIncomeDaySettlementByMerchantNoAndTrandate(ms.getMerchantNo(), ms
					.getPolicyStartDate(), enddate);
		
		MerchantPastIncome mpi=new MerchantPastIncome();
		mpi.setMerchantNo(ms.getMerchantNo());
		mpi.setIssueCompanyNo(ms.getMerchantNo().substring(0,6));
		mpi.setTranDate(trandate);
		mpi.setFeePolicyId(ms.getFeePolicyId());
		mpi.setPastIncome(realpastincome);
		mpi.setOperId(operid);
		mpi.setTranTime(new Date());
		mpi.setRemark("系统自动追溯，商户为："+ms.getMerchantNo());
		
		MerchantPastIncomeDaoImpl.insertMerchantPastIncome(mpi);
		
		//循环每一天，计算每一天应追溯的收入，并记录入数据库
		for(IncomeDaySettlement ids:ilist)
		{
			MerchantPastIncomeDetail mpid=new MerchantPastIncomeDetail();
			mpid.setMerchantNo(ms.getMerchantNo());
			mpid.setIssueCompanyNo(ids.getIssueCompanyNo());
			mpid.setTranDate(trandate);
			mpid.setFeePolicyId(ms.getFeePolicyId());
			mpid.setSaleBranchNo(ids.getSaleBranchNo());
			mpid.setOrigTranDate(ids.getTranDate());
			mpid.setMIncomeBranchId(ids.getMIncomeBranchId());
			mpid.setSIncomeBranchId(ids.getSIncomeBranchId());
			mpid.setOrigConsume(ids.getConsume().longValue());
			mpid.setOrigDeposit(ids.getDeposit().longValue());
			mpid.setOrigSettRatio(ids.getSettRatio().intValue());
			mpid.setOrigMIncome(ids.getMIncome().longValue());
			mpid.setOrigSIncome(ids.getSIncome().longValue());
			mpid.setSettRatio(ms.getFeeRatio().intValue());
			
			//计算该机构该日的新收入，因为 发卡商，销售渠道，开发渠道的分成存在变化的可能，因此需要按照老的数据计算比率后再计算
			//根据商户号，取得该商户该日的除去总公司分成后的，S与M分成的比率
			MerchantDaySettlement m=MerchantDaySettlementDaoImpl
						.getMerchantDaySettlementByTranDate_Merchantno(ids.getMerchantNo(),ids.getTranDate());
			//总公司分成
			double zong=m.getIssueFund().doubleValue();
			//总收入
			double zong_income=m.getIncome().doubleValue();
			//（总收入-总公司分成）/总收入 的比率
			double ratiowithoutzong=0;
			//除数不能为0
			if(zong_income!=0)
				ratiowithoutzong=(zong_income-zong)/zong_income;
			
			//S收入/（S收入+M收入） 的比率
			double s_r=mpid.getOrigSIncome(); //double 的原s收入
			double m_r=mpid.getOrigMIncome(); //double 的原m收入
			double ratio_news=0;
			//除数不能为0
			if((s_r+m_r)!=0)
				ratio_news=s_r/(s_r+m_r);
			
			//计算新S与M收入
			//开始计算新总收入
			double all_r=ids.getConsume().doubleValue();//double 的原有效消费
			double ratio_r=ms.getFeeRatio().doubleValue(); //double的 现行费率
			
			//计算实际的总收入，该收入包含发卡商分成与机构的分配
			double incomeall=all_r*ratio_r/10000;
			//计算出机构能分到的收入
			double branchincome=incomeall*ratiowithoutzong;
			//计算出新的S收入
			double newSincome=branchincome*ratio_news;
			//计算出新的M收入
			double newMincome=branchincome-newSincome;
			//计算出新S收入差值
			double newSincomeinterpolation=newSincome-ids.getSIncome().doubleValue()-ids.getSPastIncome().doubleValue();
			//计算出新M收入差值
			double newMincomeinterpolation=newMincome-ids.getMIncome().doubleValue()-ids.getMPastIncome().doubleValue();
			
			mpid.setSIncome(Math.round(newSincome));
			mpid.setMIncome(Math.round(newMincome));
			
			mpid.setSIncomeDiff(Math.round(newSincomeinterpolation));
			mpid.setMIncomeDiff(Math.round(newMincomeinterpolation));
			
			//插入追溯明细表
			MerchantPastIncomeDetailDaoImpl.insertMerchantPastIncomeDetail(mpid);
			
			//修改IncomeDaySettlement的已追溯收入
			ids.setSPastIncome(new BigInteger(String.valueOf(((mpid.getSIncome()+mpid.getSIncomeDiff())))));
			ids.setMPastIncome(new BigInteger(String.valueOf(((mpid.getMIncome()+mpid.getMIncomeDiff())))));
			IncomeDaySettlementDaoImpl.update(ids);
			s_realpastincome=s_realpastincome-mpid.getSIncomeDiff().longValue()-mpid.getMIncomeDiff().longValue();
		}
		
		//将实际追溯的值和剩余应该分给总公司的值做成数组返回
		return new BigInteger[]{new BigInteger(String.valueOf(realpastincome)),new BigInteger(String.valueOf(s_realpastincome))};
	}
	

}
